/******************************************************************************
 * * desktop_main.c - implementation of framework main functions
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include <time.h>
#include "desktop_global.h"
#include "ui_app_mng.h"
#include "../framework/message/phone_msg_handle.h"
#include "lv_drv_conf.h"

extern VOID Demo_128x64_Create(VOID);

/* global variate */
Framework_Mng_t g_FrameworkMng;

static lv_task_t * lowbattery_monitor_task = NULL;

/**
 * Get initialization type
 * param (in) Type: IF_FRAMEWORK_INIT_TYPE
 * return  VOID
 */
IF_FRAMEWORK_INIT_TYPE Framework_Get_Init_Type(VOID)
{
    return(g_FrameworkMng.PowerOnType);
}


/**
 * Judge whether the sim is standby
 * param (in) SimId: MMI_MODEM_SIM_ID
 * return  BOOL
 */
BOOL Framework_Is_Sim_Standby(MMI_MODEM_SIM_ID SimId)
{
    if (TRUE == g_FrameworkMng.FlightModeOn)
    {
        return(FALSE);
    }
    else
    {
        if ((FRAMEWORK_SIM_STATUS_PRESENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_1])
            && (FRAMEWORK_SIM_STATUS_PRESENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_2]))
        {
            return(g_FrameworkMng.SimStandBy[SimId]);
        }
        else
        {
            return(TRUE);
        }
    }
}


/**
 * Update signal bar
 * param (in) SimId: MMI_MODEM_SIM_ID
 * param (in) Bar: MMI_MODEM_SIGNAL_BAR
 * return  VOID
 */
VOID Phone_Modem_Signal_Bar_Ind(MMI_MODEM_SIM_ID SimId, MMI_MODEM_SIGNAL_BAR Bar)
{
    if (IF_FRAMEWORK_INIT_CHARGE == g_FrameworkMng.PowerOnType)
    {
        return;
    }

    if (FALSE == Framework_Is_Sim_Standby(SimId))
    {
        return;
    }

    if (Bar != g_FrameworkMng.SignalBar[SimId])
    {
        g_FrameworkMng.SignalBar[SimId] = Bar;
        Framework_Status_Bar_Sort(FRAMEWORK_STA_BAR_UPDATE_SIGNAL);
    }
}


/**
 * Timer stop
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Timer_Stop(VOID)
{
    if (TRUE == g_FrameworkMng.TimerRunFlg)
    {
        UI_Log_Out(UI_SUB_MODULE_FRAMEWORK, UI_LOG_LEVEL_TRACE_2, "Framework_Timer_Stop\n");
        Hal_Timer_Stop(g_FrameworkMng.TimerId);
        g_FrameworkMng.TimerRunFlg = FALSE;
    }
}


/**
 * APP register function
 * param (in) RegInfo: If_Framework_Reg_Info_t*
 * return  VOID
 */
VOID Framework_App_Register_Req(If_Framework_Reg_Info_t *RegInfo)
{
    Framework_App_t *AppList;
    Framework_App_t *App;

    if (NULL == RegInfo)
    {
        /* error */
        return;
    }

    App = (Framework_App_t *)Hal_Mem_Alloc(sizeof(Framework_App_t));
    Hal_Mem_Set(App, 0, sizeof(Framework_App_t));

    App->NameTextId = RegInfo->NameTextId;
    App->AppImage   = RegInfo->AppImage;
    App->AppFunc    = RegInfo->AppFunc;

    if (NULL == g_FrameworkMng.AppList)
    {
        g_FrameworkMng.AppList = App;
    }
    else
    {
        AppList = g_FrameworkMng.AppList;
        while (NULL != AppList->Next)
        {
            AppList = AppList->Next;
        }
        AppList->Next = App;
    }

    Hal_Mem_Free(RegInfo);
}


/**
 * Change time and date to string
 * param (in) Time: hal_rtc_t *
 * param (in) TimeStr: INT8 *
 * param (in) DateStr: INT8 *
 * return  VOID
 */
VOID Framework_Change_Time_And_Date_To_String(hal_rtc_t *TimeAndDate, INT8 *TimeStr, INT8 *DateStr)
{
    /*length of TimeStr is 13, length of DateStr is 11*/

    /* change time to string */
    if (FRAMEWORK_HOUR_FORMAT_12H == g_FrameworkMng.TimeFormat.HourFormat)
    {
        if (0 == TimeAndDate->tm_hour)
        {
            snprintf(TimeStr, 13, "12:%02d%s", TimeAndDate->tm_min, (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_AM)));
        }
        else if (12 > TimeAndDate->tm_hour)
        {
            snprintf(TimeStr, 13, "%02d:%02d%s",
                     TimeAndDate->tm_hour,
                     TimeAndDate->tm_min,
                     (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_AM)));
        }
        else if (12 == TimeAndDate->tm_hour)
        {
            snprintf(TimeStr, 13, "12:%02d%s", TimeAndDate->tm_min, (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_PM)));
        }
        else
        {
            snprintf(TimeStr, 13, "%02d:%02d%s",
                     TimeAndDate->tm_hour - 12,
                     TimeAndDate->tm_min,
                     (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_PM)));
        }
    }
    else
    {
        snprintf(TimeStr, 12, "%02d:%02d", TimeAndDate->tm_hour, TimeAndDate->tm_min);
    }

    /* change date to string */
    if (UI_LANG_EN == lv_lang_act())
    {
        snprintf(DateStr, 11, "%02d.%02d.%04d", TimeAndDate->tm_mday, TimeAndDate->tm_mon, TimeAndDate->tm_year);
    }
    else
    {
        snprintf(DateStr, 11, "%04d.%02d.%02d", TimeAndDate->tm_year, TimeAndDate->tm_mon, TimeAndDate->tm_mday);
    }
}


/**
 * Output operator of dual SIMs on Desktop interface
 * param (in) SimId: MMI_MODEM_SIM_ID
 * return  VOID
 */
VOID Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_ID SimId, lv_obj_t *Label)
{
    const INT8 * Text;

    if (NULL == Label)
    {
        /* error */
        return;
    }

    if((FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[SimId])
        || (FRAMEWORK_SIM_STATUS_UNKNOWN == g_FrameworkMng.SimStatus[SimId]))
    {
        lv_obj_set_style_local_text_color(Label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                          LV_COLOR_MAKE(90, 90, 90));
        lv_label_set_text(Label, (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_NO_SIM));
    }
    else
    {
        printf("%s: sim%d, oper %s\n", __FUNCTION__, SimId, g_FrameworkMng.Operator[SimId]);

        if(g_FrameworkMng.Operator[SimId])
        {
            if(0 == strcmp(g_FrameworkMng.Operator[SimId], "CMCC"))
            {
                Text = lv_lang_get_text(PHONE_TEXT_ID_CMCC);
            }
            else if((0 == strcmp(g_FrameworkMng.Operator[SimId], "CUCC"))
                    || (0 == strcmp(g_FrameworkMng.Operator[SimId], "UNICOM")))
            {
                Text = lv_lang_get_text(PHONE_TEXT_ID_CUCC);
            }
            else if((0 == strcmp(g_FrameworkMng.Operator[SimId], "CTCC"))
                    || (0 == strcmp(g_FrameworkMng.Operator[SimId], "CT")))
            {
                Text = lv_lang_get_text(PHONE_TEXT_ID_CTCC);
            }
            else
            {
                Text = g_FrameworkMng.Operator[SimId];
            }
        }
        else
        {
            if (FALSE == Framework_Is_Sim_Standby(SimId))
            {
                Text = lv_lang_get_text(PHONE_TEXT_ID_SIM_CLOSED);
            }
            else
            {
                printf("%s: operator NULL\n", __FUNCTION__);
                lv_label_set_text(Label, "");
                return;
            }
        }
        lv_label_set_text(Label, Text);
    }
}


/**
 * Update operator name from modem
 * param (in) SimId: MMI_MODEM_SIM_ID
 * param (in) Operator: INT8 *
 * return  VOID
 */
VOID Phone_Modem_Operator_Ind(MMI_MODEM_SIM_ID SimId, INT8 *Operator, MMI_MODEM_PLMN_RAT Rat)
{
    lv_obj_t *OperLabel = NULL;
    VOID     *Param;

    if (FALSE == Framework_Is_Sim_Standby(SimId))
    {
        printf("%s: Flight Mode %d\n", __FUNCTION__, g_FrameworkMng.FlightModeOn);
        if (NULL != Operator)
        {
            Hal_Mem_Free(Operator);
        }
        return;
    }

    printf("%s: sim%d, oper %s\n", __FUNCTION__, SimId, Operator);

    if (NULL != g_FrameworkMng.Operator[SimId])
    {
        Hal_Mem_Free(g_FrameworkMng.Operator[SimId]);
    }

    g_FrameworkMng.Operator[SimId] = Operator;

    if (ACT_ID_DESKTOP == Nav_Get_Top())
    {
        Param = Nav_Get_Param(ACT_ID_DESKTOP);
        OperLabel = ((UI_Desktop_Desc_t *)Param)->Oper_Label[SimId].Label;
    }
    else if (ACT_ID_DIAL_MAIN == Nav_Get_Top())
    {
        Param = Nav_Get_Param(ACT_ID_DIAL_MAIN);
        OperLabel = ((UI_DialPad_Desc_t *)Param)->Oper_Label[SimId].Label;
    }
    if (NULL != OperLabel)
    {
        Framework_Output_Operator_On_Desktop(SimId, OperLabel);
    }
}


/**
 * Confirmation for power up modem
 * param (in) SimId: MMI_MODEM_SIM_ID
 * return  VOID
 */
VOID Phone_Modem_Power_Up_Cnf(MMI_MODEM_SIM_ID SimId)
{
    printf("%s: simid %d\n", __FUNCTION__, SimId);

    UINT8 Offset;
    if (MMI_MODEM_SIM_1 == SimId)
    {
        Offset = 1;
    }
    else
    {
        Offset = 2;
    }
    if (0 == (g_FrameworkMng.CnfBitmap & (0x01 << Offset)))
    {
        return;
    }

    g_FrameworkMng.CnfBitmap &= ~(0x01 << Offset);

    if (0 == g_FrameworkMng.CnfBitmap)
    {
        Setting_Dual_Standby_Change_Resp();
    }
}


/**
 * Confirmation for power off modem
 * param (in) SimId: MMI_MODEM_SIM_ID
 * return  VOID
 */
VOID Phone_Modem_Power_Off_Cnf(MMI_MODEM_SIM_ID SimId)
{
    printf("%s: simid %d\n", __FUNCTION__, SimId);

    UINT8 Offset;
    if (MMI_MODEM_SIM_1 == SimId)
    {
        Offset = 3;
    }
    else
    {
        Offset = 4;
    }
    if (0 == (g_FrameworkMng.CnfBitmap & (0x01 << Offset)))
    {
        return;
    }

    g_FrameworkMng.CnfBitmap &= ~(0x01 << Offset);

    if (0 == g_FrameworkMng.CnfBitmap)
    {
        Setting_Dual_Standby_Change_Resp();
    }
} /* MMI_Modem_Power_Off_Cnf */


/**
 * Common function for phone setting changed
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Phone_Setting_Chg_Ind(Setting_Phone_Setting_t *PhoneSetting)
{
    BOOL Sim1Standby = Framework_Is_Sim_Standby(MMI_MODEM_SIM_1);
    BOOL Sim2Standby = Framework_Is_Sim_Standby(MMI_MODEM_SIM_2);

    printf("%s\n", __FUNCTION__);

    if (NULL == PhoneSetting)
    {
        /* error */
        return;
    }

    printf("%s: Sim1Standby %d, Sim2Standby %d, sim1 %d, sim 2%d\n",
           __FUNCTION__, Sim1Standby, Sim2Standby,
           g_FrameworkMng.SimStandBy[MMI_MODEM_SIM_1], g_FrameworkMng.SimStandBy[MMI_MODEM_SIM_2]);
    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_FLIGHT_MODE_ON))
    {
        printf("%s: FlightModeOn %d\n", __FUNCTION__, PhoneSetting->FlightModeOn);
        g_FrameworkMng.FlightModeOn = PhoneSetting->FlightModeOn;
    }

    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_DUAL_STAND_BY))
    {
        printf("%s: DualStandby %d\n", __FUNCTION__, PhoneSetting->DualStandby);
        switch (PhoneSetting->DualStandby)
        {
        case IF_SETTING_DUAL_SIM_STANDBY:
            if (FALSE == g_FrameworkMng.SimStandBy[0])
            {
                g_FrameworkMng.SimStandBy[0] = TRUE;
            }
            if (FALSE == g_FrameworkMng.SimStandBy[1])
            {
                g_FrameworkMng.SimStandBy[1] = TRUE;
            }
            break;

        case IF_SETTING_SIM_1_STANDBY:
            if (FALSE == g_FrameworkMng.SimStandBy[0])
            {
                g_FrameworkMng.SimStandBy[0] = TRUE;
            }
            if (TRUE == g_FrameworkMng.SimStandBy[1])
            {
                g_FrameworkMng.SimStandBy[1] = FALSE;
            }
            break;

        case IF_SETTING_SIM_2_STANDBY:
            if (TRUE == g_FrameworkMng.SimStandBy[0])
            {
                g_FrameworkMng.SimStandBy[0] = FALSE;
            }
            if (FALSE == g_FrameworkMng.SimStandBy[1])
            {
                g_FrameworkMng.SimStandBy[1] = TRUE;
            }
            break;

        default:
            /* error */
            break;
        } /* switch */
    }

    if (Sim1Standby != Framework_Is_Sim_Standby(MMI_MODEM_SIM_1))
    {
        if (TRUE == Sim1Standby)
        {
            MMI_Modem_Power_Off_Req(MMI_MODEM_SIM_1, MMI_MODEM_SIM_DISABLE);
            if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_DUAL_STAND_BY))
            {
                g_FrameworkMng.CnfBitmap |= 0x01 << 3;
            }
            g_FrameworkMng.SignalBar[MMI_MODEM_SIM_1] = MMI_MODEM_SIGNAL_BAR_0;
        }
        else
        {
            MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_1);
            if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_DUAL_STAND_BY))
            {
                g_FrameworkMng.CnfBitmap |= 0x01 << 1;
            }
        }
        if (g_FrameworkMng.Operator[MMI_MODEM_SIM_1])
        {
            Hal_Mem_Free(g_FrameworkMng.Operator[MMI_MODEM_SIM_1]);
            g_FrameworkMng.Operator[MMI_MODEM_SIM_1] = NULL;
        }
    }
    if (Sim2Standby != Framework_Is_Sim_Standby(MMI_MODEM_SIM_2))
    {
        if (TRUE == Sim2Standby)
        {
            MMI_Modem_Power_Off_Req(MMI_MODEM_SIM_2, MMI_MODEM_SIM_DISABLE);
            if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_DUAL_STAND_BY))
            {
                g_FrameworkMng.CnfBitmap |= 0x01 << 4;
            }
            g_FrameworkMng.SignalBar[MMI_MODEM_SIM_2] = MMI_MODEM_SIGNAL_BAR_0;
        }
        else
        {
            MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_2);
            if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_DUAL_STAND_BY))
            {
                g_FrameworkMng.CnfBitmap |= 0x01 << 2;
            }
        }
        if (g_FrameworkMng.Operator[MMI_MODEM_SIM_2])
        {
            Hal_Mem_Free(g_FrameworkMng.Operator[MMI_MODEM_SIM_2]);
            g_FrameworkMng.Operator[MMI_MODEM_SIM_2] = NULL;
        }
    }
    if ((0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_FLIGHT_MODE_ON))
        || (0 != g_FrameworkMng.CnfBitmap))
    {
        Framework_Status_Bar_Sort(FRAMEWORK_STA_BAR_UPDATE_SIGNAL);
    }

    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_TIME_DISPLAY))
    {
        if (IF_SETTING_TIME_HIDE == PhoneSetting->TimeDisplay.TimeDisplay)
        {
            g_FrameworkMng.TimeFormat.TimeDisplay = FRAMEWORK_TIME_HIDE;
        }
        else
        {
            g_FrameworkMng.TimeFormat.TimeDisplay = FRAMEWORK_TIME_SHOW;
        }

        if (IF_SETTING_TIME_FORMAT_12H == PhoneSetting->TimeDisplay.TimeFormat)
        {
            g_FrameworkMng.TimeFormat.HourFormat = FRAMEWORK_HOUR_FORMAT_12H;
        }
        else
        {
            g_FrameworkMng.TimeFormat.HourFormat = FRAMEWORK_HOUR_FORMAT_24H;
        }
    }

    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_AUTO_GUARD_ON))
    {
        g_FrameworkMng.AutoGuardOn = PhoneSetting->AutoGuardOn;
    }

    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_AUTO_GUARD_DELAY))
    {
        g_FrameworkMng.AutoGuardDelay = PhoneSetting->AutoGuardDelay;
    }

    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_KEYGUARD_ON))
    {
        g_FrameworkMng.KeyguardCodeOn = PhoneSetting->KeyguardOn;
    }

    if (0 != (PhoneSetting->ChangeMark & IF_SETTING_CHANGE_MARK_STANDBY_SCREEN_MODE))
    {
        if (IF_SETTING_STANDBY_SCREEN_ON == PhoneSetting->StandbyScreenMode)
        {
            g_FrameworkMng.StandbyScreenMode = TRUE;
        }
        else
        {
            g_FrameworkMng.StandbyScreenMode = FALSE;
        }
    }

    Hal_Mem_Free(PhoneSetting);
} /* Framework_Phone_Setting_Chg_Ind */


/**
 * Indicate that the phone setting has been restore
 * param (in) VOID
 * return  VOID
 */
VOID Setting_Phone_Setting_Restore_Ind(Setting_Phone_Setting_t *PhoneSetting)
{
    Framework_Phone_Setting_Chg_Ind(PhoneSetting);
}


/**
 * Phone setting change indication
 * param (in) PhoneSetting: Setting_Phone_Setting_t *
 * return  VOID
 */
VOID Setting_Phone_Setting_Chg_Ind(Setting_Phone_Setting_t *PhoneSetting)
{
    Framework_Phone_Setting_Chg_Ind(PhoneSetting);
}


/**
 * Public callback function for saving state before forward to another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Interface_OnSaveState(VOID *Ctrl)
{
    Framework_Timer_Stop();
}


/**
 * Public callback function for destroying interface which will be popped from stack
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Interface_OnDestroy(VOID *Ctrl)
{
    Framework_Timer_Stop();
    Hal_Mem_Free(Ctrl);
}


/**
 * Callback function for additional actions after creating Boot_Animation interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Boot_Animation_OnCreate(VOID *Ctrl)
{
}


/**
 * Create Boot_Animation interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Boot_Animation(VOID)
{
    UI_FullScreen_Img_Desc_t *FullScrnImgDesc;
    Nav_Func_List_t                 FuncList;

    FullScrnImgDesc =
        (UI_FullScreen_Img_Desc_t *)Hal_Mem_Alloc(sizeof(UI_FullScreen_Img_Desc_t));
    Hal_Mem_Set(FullScrnImgDesc, 0, sizeof(UI_FullScreen_Img_Desc_t));

    FullScrnImgDesc->ImgSrc = IMG_LOGO;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow    = UI_FullScreen_Img_Create;
    FuncList.OnCreate  = Framework_Boot_Animation_OnCreate;
    FuncList.OnDestroy = Framework_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_BOOT_ANIMATION, &FuncList, FullScrnImgDesc);
}


/**
 * Callback function for additional actions after creating Desktop_Unread_Sms interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_Unread_Sms_OnCreate(VOID *Ctrl)
{
    const INT8               *Text;
    INT8                     Output[30];
    UI_Desktop_Prompt_Desc_t *DesktopDesc = (UI_Desktop_Prompt_Desc_t *)Ctrl;

    Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_1,
        DesktopDesc->Oper_Label[MMI_MODEM_SIM_1].Label);
    Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_2,
        DesktopDesc->Oper_Label[MMI_MODEM_SIM_2].Label);

    if (1 < g_FrameworkMng.UnreadSmsNum)
    {
        Text = lv_lang_get_text(PHONE_TEXT_ID_UNREAD_MESSAGES);
    }
    else
    {
        Text = lv_lang_get_text(PHONE_TEXT_ID_UNREAD_MESSAGE);
    }
    sprintf(Output, "%d %s", g_FrameworkMng.UnreadSmsNum, Text);

    lv_label_set_text(DesktopDesc->ContLabel.Label, Output);

    if(TRUE == g_FrameworkMng.AutoGuardOn)
    {
        g_FrameworkMng.KeyGuardTimer = 0;
    }
}


/**
 * Callback function for restoring state on Desktop_Unread_Sms interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_Unread_Sms_OnRestoreState(VOID *Ctrl)
{
    if (0 == g_FrameworkMng.UnreadSmsNum)
    {
        Nav_Home(ACT_ID_ANY);
    }
    else
    {
        Framework_Desktop_Unread_Sms_OnCreate(Ctrl);
    }
}


/**
 * Callback function for handling key pressed on Desktop_Unread_Sms interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Desktop_Unread_Sms_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta,
    UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
        case KEY_END:
            g_FrameworkMng.UnreadSmsNum = 0;
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_OK:
            g_FrameworkMng.UnreadSmsNum = 0;
            Framework_Sms_Open_Inbox_Req();
            break;

        default:
            break;
        } /* switch */
    }

    return(1);
}


/**
 * Create Desktop_Unread_Sms interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Desktop_Unread_Sms(VOID)
{
    UI_Desktop_Prompt_Desc_t *DesktopDesc;
    Nav_Func_List_t          FuncList;

    if (0 == g_FrameworkMng.UnreadSmsNum)
    {
        /* error */
        return;
    }

    DesktopDesc = (UI_Desktop_Prompt_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Desktop_Prompt_Desc_t));
    Hal_Mem_Set(DesktopDesc, 0, sizeof(UI_Desktop_Prompt_Desc_t));

    /* create Desktop interface */
    DesktopDesc->Oper_Label[0].TxtId      = LV_LANG_TXT_ID_NONE;
    DesktopDesc->Oper_Label[0].TxtAlign   = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->Oper_Label[0].LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    if (FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_1])
    {
        DesktopDesc->Oper_Label[0].ImgSrc = SYMBOL_NO_SIM1;
    }
    else
    {
        DesktopDesc->Oper_Label[0].ImgSrc = SYMBOL_SIM1;
    }
    DesktopDesc->Oper_Label[1].TxtId      = LV_LANG_TXT_ID_NONE;
    DesktopDesc->Oper_Label[1].TxtAlign   = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->Oper_Label[1].LabelAlign = LV_ALIGN_OUT_BOTTOM_LEFT;
    if (FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_2])
    {
        DesktopDesc->Oper_Label[1].ImgSrc = SYMBOL_NO_SIM2;
    }
    else
    {
        DesktopDesc->Oper_Label[1].ImgSrc = SYMBOL_SIM2;
    }
    DesktopDesc->ContLabel.TxtId          = LV_LANG_TXT_ID_NONE;
    DesktopDesc->ContLabel.TxtAlign       = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->ContLabel.LabelAlign     = LV_ALIGN_OUT_BOTTOM_LEFT;

    DesktopDesc->ButtonBar.ButtonL.Valid = FALSE;
    DesktopDesc->ButtonBar.ButtonM.Valid = TRUE;
    DesktopDesc->ButtonBar.ButtonM.TxtId = PHONE_TEXT_ID_LIST;
    DesktopDesc->ButtonBar.ButtonR.Valid = TRUE;
    DesktopDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    DesktopDesc->KeyFunc                 = Framework_Desktop_Unread_Sms_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Desktop_Prompt_Create;
    FuncList.OnCreate       = Framework_Desktop_Unread_Sms_OnCreate;
    FuncList.OnRestoreState = Framework_Desktop_Unread_Sms_OnRestoreState;
    FuncList.OnDestroy      = Framework_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_DESKTOP_UNREAD_SMS, &FuncList, DesktopDesc);
} /* Framework_Create_Desktop_Unread_Sms */


/**
 * Callback function for additional actions after creating Desktop_Missed_Call interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_Missed_Call_OnCreate(VOID *Ctrl)
{
    const INT8               *Text;
    INT8                     Output[30];
    UI_Desktop_Prompt_Desc_t *DesktopDesc = (UI_Desktop_Prompt_Desc_t *)Ctrl;

    Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_1,
        DesktopDesc->Oper_Label[MMI_MODEM_SIM_1].Label);
    Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_2,
        DesktopDesc->Oper_Label[MMI_MODEM_SIM_2].Label);

    if (1 < g_FrameworkMng.UnreadMissedCallNum)
    {
        Text = lv_lang_get_text(PHONE_TEXT_ID_UNREAD_MISSED_CALLS);
    }
    else
    {
        Text = lv_lang_get_text(PHONE_TEXT_ID_UNREAD_MISSED_CALL);
    }
    sprintf(Output, "%d %s", g_FrameworkMng.UnreadMissedCallNum, Text);

    lv_label_set_text(DesktopDesc->ContLabel.Label, Output);

    if(TRUE == g_FrameworkMng.AutoGuardOn)
    {
        g_FrameworkMng.KeyGuardTimer = 0;
    }
}


/**
 * Callback function for restoring state on Desktop_Missed_Call interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_Missed_Call_OnRestoreState(VOID *Ctrl)
{
    if (0 == g_FrameworkMng.UnreadMissedCallNum)
    {
        Nav_Home(ACT_ID_ANY);
    }
    else
    {
        Framework_Desktop_Missed_Call_OnCreate(Ctrl);
    }
}


/**
 * Callback function for handling key pressed on Desktop_Missed_Call interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Desktop_Missed_Call_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta,
    UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
        case KEY_END:
            g_FrameworkMng.UnreadMissedCallNum = 0;
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_OK:
            g_FrameworkMng.UnreadMissedCallNum = 0;
            CallLog_Framework_Open_Missed_Call_List_Req();
            break;

        default:
            break;
        } /* switch */
    }

    return(1);
}


/**
 * Create Desktop_Missed_Call interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Desktop_Missed_Call(VOID)
{
    UI_Desktop_Prompt_Desc_t *DesktopDesc;
    Nav_Func_List_t          FuncList;

    DesktopDesc = (UI_Desktop_Prompt_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Desktop_Prompt_Desc_t));
    Hal_Mem_Set(DesktopDesc, 0, sizeof(UI_Desktop_Prompt_Desc_t));

    /* create Desktop interface */
    DesktopDesc->Oper_Label[0].TxtId      = LV_LANG_TXT_ID_NONE;
    DesktopDesc->Oper_Label[0].TxtAlign   = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->Oper_Label[0].LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    if (FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_1])
    {
        DesktopDesc->Oper_Label[0].ImgSrc = SYMBOL_NO_SIM1;
    }
    else
    {
        DesktopDesc->Oper_Label[0].ImgSrc = SYMBOL_SIM1;
    }
    DesktopDesc->Oper_Label[1].TxtId      = LV_LANG_TXT_ID_NONE;
    DesktopDesc->Oper_Label[1].TxtAlign   = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->Oper_Label[1].LabelAlign = LV_ALIGN_OUT_BOTTOM_LEFT;
    if (FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_2])
    {
        DesktopDesc->Oper_Label[1].ImgSrc = SYMBOL_NO_SIM2;
    }
    else
    {
        DesktopDesc->Oper_Label[1].ImgSrc = SYMBOL_SIM2;
    }
    DesktopDesc->ContLabel.TxtId          = LV_LANG_TXT_ID_NONE;
    DesktopDesc->ContLabel.TxtAlign       = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->ContLabel.LabelAlign     = LV_ALIGN_OUT_BOTTOM_LEFT;

    DesktopDesc->ButtonBar.ButtonL.Valid = FALSE;
    DesktopDesc->ButtonBar.ButtonM.Valid = TRUE;
    DesktopDesc->ButtonBar.ButtonM.TxtId = PHONE_TEXT_ID_LIST;
    DesktopDesc->ButtonBar.ButtonR.Valid = TRUE;
    DesktopDesc->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;
    DesktopDesc->KeyFunc                 = Framework_Desktop_Missed_Call_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Desktop_Prompt_Create;
    FuncList.OnCreate       = Framework_Desktop_Missed_Call_OnCreate;
    FuncList.OnRestoreState = Framework_Desktop_Missed_Call_OnRestoreState;
    FuncList.OnSaveState    = Framework_Interface_OnSaveState;
    FuncList.OnDestroy      = Framework_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_DESKTOP_MISSED_CALL, &FuncList, DesktopDesc);
} /* Framework_Create_Desktop_Missed_Call */


/**
 * LCD wakeup or sleep
 * param (in) Wakeup: BOOL
 * return VOID:
 */
VOID Framework_Set_Lcd_Status(BOOL Wakeup)
{
    printf("%s: wakeup %d, LcdStatus %d\n", __FUNCTION__, Wakeup, g_FrameworkMng.LcdStatus);
    if(Wakeup == g_FrameworkMng.LcdStatus) return;

    g_FrameworkMng.LcdStatus = Wakeup;
    if(Wakeup) {
        Hal_Lcd_Wakeup();
#if USE_LV_WLAN != 0
        hal_wlan_lcd_wakeup();
#endif
    } else
        Hal_Lcd_Sleep();
}

/**
 * Suspend enable or disable
 * param (in) enable: BOOL
 * return VOID:
 */
VOID Framework_Set_Suspend_Enable(BOOL Enable)
{
    printf("%s: %d\n", __FUNCTION__, Enable);
    if(Enable == g_FrameworkMng.SuspendEnable)
        return;
    g_FrameworkMng.SuspendEnable = Enable;
}


/**
 * LCD wakeup or sleep
 * param (in) VOID
 * return BOOL
 */
BOOL Framework_Get_Lcd_Status(VOID)
{
    return(g_FrameworkMng.LcdStatus);
}


/**
 * Restart backlight timer
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Restart_Backlight_Timer(VOID)
{
    g_FrameworkMng.BacklightTimer = 0;
}


/**
 * calculate the difference between the two times
 * param (in) OldTime: hal_rtc_t *
 * param (in) NewTime: hal_rtc_t *
 * return  UINT32: in seconds
 */
UINT32 Framework_Time_Difference(hal_rtc_t *OldTime, hal_rtc_t *NewTime)
{
    struct tm Old;
    struct tm New;
    UINT32 Diff;

    Old.tm_year = OldTime->tm_year;
    Old.tm_mon  = OldTime->tm_mon;
    Old.tm_mday = OldTime->tm_mday;
    Old.tm_hour = OldTime->tm_hour;
    Old.tm_min  = OldTime->tm_min;
    Old.tm_sec  = OldTime->tm_sec;

    New.tm_year = NewTime->tm_year;
    New.tm_mon  = NewTime->tm_mon;
    New.tm_mday = NewTime->tm_mday;
    New.tm_hour = NewTime->tm_hour;
    New.tm_min  = NewTime->tm_min;
    New.tm_sec  = NewTime->tm_sec;

    Diff = mktime(&New) - mktime(&Old);
    return Diff;
}


/**
 * Suspend or resume gui task
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Suspend(VOID)
{
    hal_rtc_t OldTime;
    hal_rtc_t NewTime;
    UINT32    WakeupFlag = 0;

    if(FALSE == g_FrameworkMng.SuspendEnable) {
        printf("%s:suspend disable\n",__FUNCTION__);
        return;
    }

    Framework_Set_Lcd_Status(FALSE);

    if(TRUE == g_FrameworkMng.SleepLcdOnly) {
        return;
    }

    Hal_Rtc_Gettime(&OldTime);

    while (1)
    {
        WakeupFlag = Hal_Pm_Suspend(); /*suspend gui task*/
        printf("%s: wakeupflag %d\n", __FUNCTION__, WakeupFlag);
        Hal_Pm_Resume();
        if(PM_RESUME_ALL & WakeupFlag)
        {
            Hal_Rtc_Gettime(&NewTime);
            g_FrameworkMng.KeyGuardTimer += Framework_Time_Difference(&OldTime, &NewTime);
            Framework_Check_Keyguard_Timer();

            if(((PM_RESUME_UI & WakeupFlag)
               && (MODEM_WAKE_UP_RING == MMI_Modem_Adp_Get_Wakeup_Reason_Req()))
               || (TRUE == g_FrameworkMng.SleepLcdOnly))
            {
                /*wait for the response of call*/
                return;
            }
#if 0
            else if (PM_RESUME_NORMALKEY & WakeupFlag)
            {
                if (ACT_ID_KEY_GUARD == Nav_Get_Top())
                {
                    /*not end key,  not wakeup*/
                    continue;
                }
            }
#endif
            g_FrameworkMng.KeyGuardTimer = 0;
            g_FrameworkMng.BacklightTimer = 0;
            Framework_Update_Status(TRUE);
            Framework_Set_Lcd_Status(TRUE);
        }
        break;
    }
}


/**
 * update every second
 * param (in) Para: VOID *
 * return  VOID
 */
VOID Framework_1s_Update_Cb(lv_task_t * Task)
{
    UINT32 BacklightPeriod = Setting_Get_Backlight_Timer_Length();
    ACTIVITY_ID TopActId = Nav_Get_Top();

    if (1000 >= lv_disp_get_inactive_time(NULL))
    {
        /*key pressed*/
        // printf("%s: key pressed\n", __FUNCTION__);
        g_FrameworkMng.BacklightTimer = 0;
        g_FrameworkMng.KeyGuardTimer  = 0;
    }
    else
    {
        g_FrameworkMng.BacklightTimer++;
        g_FrameworkMng.KeyGuardTimer++;
    }

    if ((BacklightPeriod <= g_FrameworkMng.BacklightTimer)
       && ((ACT_ID_CALL_EMERGENCY_CALLING > TopActId)
           || (ACT_ID_CALL_DTMF_INPUT < TopActId))
       && (ACT_ID_ALARM_RING != TopActId)
       && (ACT_ID_CALENDAR_REMINDER_ALARM_RING != TopActId))
    {
        Framework_Suspend();
    }
    else
    {
        Framework_Check_Keyguard_Timer();
        Framework_Update_Status(FALSE);
    }
}


/**
 * Suspend or resume gui task during power off
 * param (in) VOID
 * return  VOID
 */
VOID Framework_PowerOff_Suspend(VOID)
{
    UINT32 WakeupFlag = 0;

    Framework_Set_Lcd_Status(FALSE);

    WakeupFlag = Hal_Pm_Suspend(); /*suspend gui task*/
    printf("%s: wakeupflag %d\n", __FUNCTION__, WakeupFlag);
    Hal_Pm_Resume();
    if(PM_RESUME_ALL & WakeupFlag)
    {
        if (PM_RESUME_USB & WakeupFlag)
        {
            /*stop charging when suspend in charging mode*/
            lv_task_set_prio(g_FrameworkMng.Task, LV_TASK_PRIO_OFF);
            Framework_Set_Phone_Ready_Status(FALSE);
            Hal_Power_Off(HAL_TYPE_POWER_OFF);
            return;
        }

        g_FrameworkMng.BacklightTimer = 0;
        if (0 == (PM_RESUME_ALARM & WakeupFlag))
        {
            /*status bar will be created when alarm begins to ring,
             *so not update status for alarm event*/
            Framework_PowerOff_Update_Status();
        }
        Framework_Set_Lcd_Status(TRUE);
    }
}


/**
 * update every second during power off
 * param (in) Para: VOID *
 * return  VOID
 */
VOID Framework_PowerOff_1s_Update_Cb(lv_task_t * Task)
{
    UINT32 BacklightPeriod = FRAMEWORK_POWEROFF_BACKLIGHT_PERIOD; // in seconds
    ACTIVITY_ID TopActId = Nav_Get_Top();
    BOOL        PowerOff = FALSE;

    if ((FALSE == g_FrameworkMng.ChargeFlg) && (ACT_ID_CHARGE_ANIMATION == TopActId))
    {
        PowerOff = TRUE;
        Framework_Set_Phone_Ready_Status(FALSE);
        Hal_Power_Off(HAL_TYPE_POWER_OFF);
    }

    if (1000 >= lv_disp_get_inactive_time(NULL))
    {
        /*key pressed*/
        printf("%s: key pressed\n", __FUNCTION__);
        g_FrameworkMng.BacklightTimer = 0;
        if ((0 != Hal_Pm_Get_State())
            && (FALSE == g_FrameworkMng.LcdStatus)
            && (FALSE == PowerOff))
        {
            Framework_Set_Lcd_Status(TRUE);
        }
    }
    else if ((ACT_ID_ALARM_RING != TopActId)
        && (ACT_ID_CALENDAR_REMINDER_ALARM_RING != TopActId))
    {
        g_FrameworkMng.BacklightTimer++;
    }

    if (FALSE == g_FrameworkMng.LcdStatus)
    {
        return;
    }

    if (BacklightPeriod <= g_FrameworkMng.BacklightTimer)
    {
        if (ACT_ID_ASK_ABOUT_POWER_ON == TopActId)
        {
            Framework_Set_Phone_Ready_Status(FALSE);
            Hal_Power_Off(HAL_TYPE_POWER_OFF);
        }
        else if (ACT_ID_CHARGE_ANIMATION == TopActId)
        {
            Framework_PowerOff_Suspend();
        }
        else
        {
            printf("%s: error interface id %d\n", __FUNCTION__, TopActId);
        }
    }
    else
    {
        Framework_PowerOff_Update_Status();
    }
}


UI_PHONE_TEXT_ID Framework_Get_Week_Text_Id(UINT8 Wday)
{
    switch (Wday)
    {
    case 0:
        return(PHONE_TEXT_ID_WDAY_SUNDAY);

    case 1:
        return(PHONE_TEXT_ID_WDAY_MONDAY);

    case 2:
        return(PHONE_TEXT_ID_WDAY_TUESDAY);

    case 3:
        return(PHONE_TEXT_ID_WDAY_WEDNESDAY);

    case 4:
        return(PHONE_TEXT_ID_WDAY_THURSDAY);

    case 5:
        return(PHONE_TEXT_ID_WDAY_FRIDAY);

    case 6:
        return(PHONE_TEXT_ID_WDAY_SATURDAY);

    default:
        printf("%s: wrong wday %d\n", __FUNCTION__, Wday);
        return(PHONE_TEXT_ID_WDAY_SUNDAY);
    }
}


/**
 * Callback function for additional actions after Creating Desktop interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_OnCreate(VOID *Ctrl)
{
    hal_rtc_t         TimeAndDate;
    hal_rtc_t         RtcAlarm;
    INT8              TimeStr[13]  = { 0 };
    INT8              DateStr[11]  = { 0 };
    UI_Desktop_Desc_t *DesktopDesc = (UI_Desktop_Desc_t *)Ctrl;
    lv_obj_t          *StatusBar;

    Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_1,
        DesktopDesc->Oper_Label[MMI_MODEM_SIM_1].Label);
    Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_2,
        DesktopDesc->Oper_Label[MMI_MODEM_SIM_2].Label);

    Hal_Rtc_Gettime(&TimeAndDate);
    if (FRAMEWORK_TIME_SHOW == g_FrameworkMng.TimeFormat.TimeDisplay)
    {
        Framework_Change_Time_And_Date_To_String(&TimeAndDate, TimeStr, DateStr);

        lv_label_set_text(DesktopDesc->ContLabel[0].Label, TimeStr);
        lv_label_set_text(DesktopDesc->ContLabel[1].Label, DateStr);
        lv_label_set_text_id(DesktopDesc->ContLabel[2].Label,
                             Framework_Get_Week_Text_Id(TimeAndDate.tm_wday));
    }

    StatusBar = lv_obj_get_parent(g_FrameworkMng.LabelBattery);
    lv_obj_set_parent(StatusBar, DesktopDesc->Img);

    lv_task_create(Framework_1s_Update_Cb, 1000, LV_TASK_PRIO_HIGH, NULL);

    if(TRUE == g_FrameworkMng.AutoGuardOn)
    {
        g_FrameworkMng.KeyGuardTimer = 0;
    }

    if (g_FrameworkMng.KeyguardCodeOn)
    {
        Framework_Create_Desktop_Unlock();
    }

    Hal_Rtc_Get_Alarm(RTC_ALARM_1, &RtcAlarm);
    if ((RtcAlarm.tm_year == TimeAndDate.tm_year)
        && (RtcAlarm.tm_mon == TimeAndDate.tm_mon)
        && (RtcAlarm.tm_mday == TimeAndDate.tm_mday)
        && (RtcAlarm.tm_hour == TimeAndDate.tm_hour)
        && (RtcAlarm.tm_min == TimeAndDate.tm_min))
    {
        Framework_Alarm_PowerOff_Alarm_Req();
    }
    else
    {
        Framework_Alarm_PowerOn_Complete_Req();
    }
    #if USE_LV_BLUETOOTH != 0
    extern VOID Bluetooth_Start_Without_UI(VOID);
    Bluetooth_Start_Without_UI();
    #endif
    #if USE_LV_WLAN != 0
    Setting_Wlan_Init();
    #endif
}


/**
 * Callback function for saving state on Desktop interface before forward to another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_OnSaveState(VOID *Ctrl)
{
    lv_obj_t *StatusBar;

    StatusBar = lv_obj_get_parent(g_FrameworkMng.LabelBattery);
    lv_obj_set_parent(StatusBar, FP_PARENT);

    Framework_Timer_Stop();
}


/**
 * Callback function for restoring state on Desktop interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Desktop_OnRestoreState(VOID *Ctrl)
{
    hal_rtc_t            TimeAndDate;
    INT8                 TimeStr[13] = { 0 };
    INT8                 DateStr[11] = { 0 };
    lv_obj_t             *StatusBar;
    UI_Desktop_Desc_t    *DesktopDesc = (UI_Desktop_Desc_t *)Ctrl;
    Setting_Wall_Paper_t *SettingWallPaper;

    printf("%s: missed call %d, unread SMS %d, lock %d\n",
           __FUNCTION__, g_FrameworkMng.UnreadMissedCallNum, g_FrameworkMng.UnreadSmsNum,
        g_FrameworkMng.KeyGuardLock);

    if (TRUE == g_FrameworkMng.KeyGuardLock)
    {
        Framework_Create_Desktop_Unlock();
    }
    else if (0 != g_FrameworkMng.UnreadMissedCallNum)
    {
        Framework_Create_Desktop_Missed_Call();
    }
    else if (0 != g_FrameworkMng.UnreadSmsNum)
    {
        Framework_Create_Desktop_Unread_Sms();
    }
    else
    {   /* create Desktop */
        Setting_Get_Wall_Paper_Req(&SettingWallPaper);
        if (SettingWallPaper != DesktopDesc->Wall_Paper_Img)
        {
            DesktopDesc->Wall_Paper_Img = SettingWallPaper;
            lv_img_set_src(DesktopDesc->Img, SettingWallPaper);
        }

        Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_1,
            DesktopDesc->Oper_Label[MMI_MODEM_SIM_1].Label);
        Framework_Output_Operator_On_Desktop(MMI_MODEM_SIM_2,
            DesktopDesc->Oper_Label[MMI_MODEM_SIM_2].Label);

        if (FRAMEWORK_TIME_SHOW == g_FrameworkMng.TimeFormat.TimeDisplay)
        {
            Hal_Rtc_Gettime(&TimeAndDate);
            Framework_Change_Time_And_Date_To_String(&TimeAndDate, TimeStr, DateStr);

            lv_label_set_text(DesktopDesc->ContLabel[0].Label, TimeStr);
            lv_label_set_text(DesktopDesc->ContLabel[1].Label, DateStr);
            lv_label_set_text_id(DesktopDesc->ContLabel[2].Label,
                                 Framework_Get_Week_Text_Id(TimeAndDate.tm_wday));
        }

        StatusBar = lv_obj_get_parent(g_FrameworkMng.LabelBattery);
        lv_obj_set_parent(StatusBar, DesktopDesc->Img);

        if(TRUE == g_FrameworkMng.AutoGuardOn)
        {
            g_FrameworkMng.KeyGuardTimer = 0;
        }
    }
} /* Framework_Desktop_OnRestoreState */


/**
 * Open the specified APP on Desktop interface
 * param (in) AppTextId: UINT16
 * return  VOID
 */
VOID Framework_Desktop_Enter_App(UINT16 AppTextId)
{
    Framework_App_t *AppList = g_FrameworkMng.AppList;

    while (NULL != AppList)
    {
        if (AppTextId == AppList->NameTextId)
        {
            break;
        }
        else
        {
            AppList = AppList->Next;
        }
    }

    if (NULL == AppList)
    {
        UI_Log_Out(UI_SUB_MODULE_FRAMEWORK, UI_LOG_LEVEL_TRACE_3, "APP not registered, TextId %d\n",
            AppTextId);
    }
    else
    {
        AppList->AppFunc();
    }
}


/**
 * Callback function for handling key pressed on Desktop interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Desktop_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    INT8  *String = NULL;
    INT8  Char    = 0;
    UINT8 Digit   = 0;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_0:
            Char = '0';
            break;

        case KEY_1:
            Char = '1';
            break;

        case KEY_2:
            Char = '2';
            break;

        case KEY_3:
            Char = '3';
            break;

        case KEY_4:
            Char = '4';
            break;

        case KEY_5:
            Char = '5';
            break;

        case KEY_6:
            Char = '6';
            break;

        case KEY_7:
            Char = '7';
            break;

        case KEY_8:
            Char = '8';
            break;

        case KEY_9:
            Char = '9';
            break;

        case KEY_ASTERISK:
            Char = '*';
            break;

        case KEY_HASH:
            Char = '#';
            break;

        case KEY_SOFTLEFT:
            Framework_Create_Goto();
            break;

        case KEY_SOFTRIGHT:
            Framework_Desktop_Enter_App(PHONE_TEXT_ID_ALARM);
            break;

        case KEY_DIAL:
            CallLog_Framework_Open_Dialed_Number_List_Req();
            break;

        case KEY_END:
            Framework_Create_Switch_Off();
            break;

        case KEY_UP:
            /* pending for flashlight */
            break;

        case KEY_DOWN:
            Framework_Desktop_Enter_App(PHONE_TEXT_ID_CONTACT);
            break;

        case KEY_LEFT:
            Framework_Sms_Send_Message_Req("");
            break;

        case KEY_RIGHT:
            Framework_Desktop_Enter_App(PHONE_TEXT_ID_CALENDAR);
            break;

        case KEY_OK:
            Framework_Call_Menu_Main();
            break;

        default:
            break;
        } /* switch */

        if (0 != Char)
        {
            String    = (INT8 *)Hal_Mem_Alloc(sizeof(INT8) * 2);
            String[0] = Char;
            String[1] = '\0';
            Framework_Create_Dial_Main(String);
        }
    }
    else if (KEY_LONGPRESS == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_2:
            Digit = 2;
            break;

        case KEY_3:
            Digit = 3;
            break;

        case KEY_4:
            Digit = 4;
            break;

        case KEY_5:
            Digit = 5;
            break;

        case KEY_6:
            Digit = 6;
            break;

        case KEY_7:
            Digit = 7;
            break;

        case KEY_8:
            Digit = 8;
            break;

        case KEY_9:
            Digit = 9;
            break;

        default:
            break;
        }

        if (0 != Digit)
        {
            String = Contacts_Get_Speed_Dial_Number_Req(Digit);

            if (NULL != String)
            {
                Call_Framework_Voice_Call_Req(String);
            }
        }
    }

    return(1);
} /* Framework_Desktop_Key_Cb */


/**
 * Create Desktop interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Desktop(VOID)
{
    UI_Desktop_Desc_t *DesktopDesc;
    Nav_Func_List_t   FuncList;

    DesktopDesc = (UI_Desktop_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Desktop_Desc_t));
    Hal_Mem_Set(DesktopDesc, 0, sizeof(UI_Desktop_Desc_t));

    Setting_Get_Wall_Paper_Req(&DesktopDesc->Wall_Paper_Img);
    DesktopDesc->Oper_Label[0].TxtId      = LV_LANG_TXT_ID_NONE;
    DesktopDesc->Oper_Label[0].TxtAlign   = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->Oper_Label[0].LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    if (FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_1])
    {
        DesktopDesc->Oper_Label[0].ImgSrc = SYMBOL_NO_SIM1;
    }
    else
    {
        DesktopDesc->Oper_Label[0].ImgSrc = SYMBOL_SIM1;
    }
    DesktopDesc->Oper_Label[1].TxtId      = LV_LANG_TXT_ID_NONE;
    DesktopDesc->Oper_Label[1].TxtAlign   = LV_LABEL_ALIGN_LEFT;
    DesktopDesc->Oper_Label[1].LabelAlign = LV_ALIGN_OUT_BOTTOM_LEFT;
    if (FRAMEWORK_SIM_STATUS_ABSENT == g_FrameworkMng.SimStatus[MMI_MODEM_SIM_2])
    {
        DesktopDesc->Oper_Label[1].ImgSrc = SYMBOL_NO_SIM2;
    }
    else
    {
        DesktopDesc->Oper_Label[1].ImgSrc = SYMBOL_SIM2;
    }
    DesktopDesc->ContLabel[0].TxtId       = LV_LANG_TXT_ID_NONE;
    DesktopDesc->ContLabel[0].TxtAlign    = LV_LABEL_ALIGN_CENTER;
    DesktopDesc->ContLabel[0].LabelAlign  = LV_ALIGN_OUT_BOTTOM_LEFT;
    DesktopDesc->ContLabel[0].TxtFont     = LV_THEME_SIMPLE_FONT_SMALL;
    DesktopDesc->ContLabel[1].TxtId       = LV_LANG_TXT_ID_NONE;
    DesktopDesc->ContLabel[1].TxtAlign    = LV_LABEL_ALIGN_CENTER;
    DesktopDesc->ContLabel[1].LabelAlign  = LV_ALIGN_OUT_BOTTOM_LEFT;
    DesktopDesc->ContLabel[2].TxtId       = LV_LANG_TXT_ID_NONE;
    DesktopDesc->ContLabel[2].TxtAlign    = LV_LABEL_ALIGN_CENTER;
    DesktopDesc->ContLabel[2].LabelAlign  = LV_ALIGN_OUT_BOTTOM_LEFT;
    DesktopDesc->ButtonBar.ButtonL.Valid  = TRUE;
    DesktopDesc->ButtonBar.ButtonL.TxtId  = PHONE_TEXT_ID_GOTO;
    DesktopDesc->ButtonBar.ButtonM.Valid  = TRUE;
    DesktopDesc->ButtonBar.ButtonM.TxtId  = PHONE_TEXT_ID_MENU;
    DesktopDesc->ButtonBar.ButtonR.Valid  = TRUE;
    DesktopDesc->ButtonBar.ButtonR.TxtId  = PHONE_TEXT_ID_ALARM;
    DesktopDesc->KeyFunc                  = Framework_Desktop_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Desktop_Create;
    FuncList.OnCreate       = Framework_Desktop_OnCreate;
    FuncList.OnRestoreState = Framework_Desktop_OnRestoreState;
    FuncList.OnSaveState    = Framework_Desktop_OnSaveState;

    Nav_Forward(ACT_ID_ANY, ACT_ID_DESKTOP, &FuncList, DesktopDesc);
} /* Framework_Create_Desktop */


/**
 * Action if timer expired for interface migration on Welcome_Note interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Welcome_Note_Timeout(VOID* Para)
{
    UI_Log_Out(UI_SUB_MODULE_FRAMEWORK, UI_LOG_LEVEL_TRACE_1, "Framework_Welcome_Note_Timeout\n");

    g_FrameworkMng.TimerRunFlg = FALSE;

    /* Destroy Welcome_Note interface */
    Nav_Back(ACT_ID_ANY);

    Framework_Set_Phone_Ready_Status(TRUE);

#ifdef USE_LV_INTERPHONE_DEMO
    Interphone_Create_Login();
#elif USE_LV_DEMO_128x64
    Demo_128x64_Create();
#else
    Framework_Create_Desktop();
#endif
}


/**
 * Callback function for additional actions after Creating Welcome_Note interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Welcome_Note_OnCreate(VOID *Ctrl)
{
    lv_obj_t * Label = ((UI_FullScreen_Label_Only_Desc_t *)Ctrl)->ContLabel.Label;
    lv_label_set_text(Label, g_FrameworkMng.WelcomeNote);
    Hal_Mem_Free(g_FrameworkMng.WelcomeNote);
    lv_obj_align(Label, lv_obj_get_parent(Label), LV_ALIGN_CENTER, 0, 0);

    UINT8 Para = 0;
    g_FrameworkMng.TimerId = Hal_Timer_Start(FRAMEWORK_TIMER_WELCOME_NOTE_LENGTH, Framework_Welcome_Note_Timeout, (VOID *)&Para, FALSE);
    g_FrameworkMng.TimerRunFlg = TRUE;
}


/**
 * Create Welcome_Note interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Welcome_Note(VOID)
{
    UI_FullScreen_Label_Only_Desc_t *FullScrnLblOnlyDesc;
    Nav_Func_List_t                 FuncList;

    UI_Log_Out(UI_SUB_MODULE_FRAMEWORK, UI_LOG_LEVEL_TRACE_1, "Framework_Create_Welcome_Note\n");

    FullScrnLblOnlyDesc =
        (UI_FullScreen_Label_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_FullScreen_Label_Only_Desc_t));
    Hal_Mem_Set(FullScrnLblOnlyDesc, 0, sizeof(UI_FullScreen_Label_Only_Desc_t));

    FullScrnLblOnlyDesc->ContLabel.TxtId = LV_LANG_TXT_ID_NONE;
    /* FullScrnLblOnlyDesc->ContLabel.TxtFont = &lv_font_dejavu_20; */
    FullScrnLblOnlyDesc->ContLabel.LabelAlign = LV_ALIGN_CENTER;
    FullScrnLblOnlyDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_CENTER;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow    = UI_FullScreen_Label_Only_Create;
    FuncList.OnCreate  = Framework_Welcome_Note_OnCreate;
    FuncList.OnDestroy = Framework_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_WELCOME_NOTE, &FuncList, FullScrnLblOnlyDesc);
}


/**
 * Callback function for additional actions after creating Charge_Animation interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Charge_Animation_OnCreate(VOID *Ctrl)
{
    UI_FullScreen_Label_Desc_t *Interface = (UI_FullScreen_Label_Desc_t *)Ctrl;

    if (NULL != Interface->ChargeLabel.Label)
    {
        lv_obj_del(Interface->ChargeLabel.Label);
    }

    if (HAL_BAT_FULL != g_FrameworkMng.BatteryStatus)
    {
        Framework_Play_Charging_Anim(Interface->BatteryLabel.Label);
    }

    Framework_Alarm_PowerOn_Complete_Req();
}


/**
 * Callback function for restoring state on Charge_Animation interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Charge_Animation_OnRestoreState(VOID *Ctrl)
{
    UI_FullScreen_Label_Desc_t *Interface = (UI_FullScreen_Label_Desc_t *)Ctrl;

    if (NULL != Interface->ChargeLabel.Label)
    {
        lv_obj_del(Interface->ChargeLabel.Label);
    }

    lv_label_set_text(Interface->BatteryLabel.Label,
        Framework_Get_Battery_Symbol(g_FrameworkMng.BatteryStatus));

    if (HAL_BAT_FULL != g_FrameworkMng.BatteryStatus)
    {
        Framework_Play_Charging_Anim(Interface->BatteryLabel.Label);
    }
}


/**
 * Callback function for saving state on Charge_Animation interface before forward to another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Framework_Charge_Animation_OnSaveState(VOID *Ctrl)
{
    lv_obj_t *Label_Battery = ((UI_FullScreen_Label_Desc_t *)Ctrl)->BatteryLabel.Label;

    if (HAL_BAT_FULL != g_FrameworkMng.BatteryStatus)
    {
        lv_anim_del(Label_Battery, Framework_Charging_Anim);
    }
}


/**
 * Save phone setting
 * param (in) PhoneSetting: Setting_Phone_Setting_t *
 * return  VOID
 */
VOID Framework_Save_Phone_Setting(Setting_Phone_Setting_t *PhoneSetting)
{
    /* save parameters to g_FrameworkMng */
    printf("%s: DualStandby %d, FlightModeOn %d\n",
           __FUNCTION__, PhoneSetting->DualStandby, PhoneSetting->FlightModeOn);
    if (IF_SETTING_DUAL_SIM_STANDBY == PhoneSetting->DualStandby)
    {
        g_FrameworkMng.SimStandBy[0] = TRUE;
        g_FrameworkMng.SimStandBy[1] = TRUE;
    }
    else if (IF_SETTING_SIM_1_STANDBY == PhoneSetting->DualStandby)
    {
        g_FrameworkMng.SimStandBy[0] = TRUE;
        g_FrameworkMng.SimStandBy[1] = FALSE;
    }
    else if (IF_SETTING_SIM_2_STANDBY == PhoneSetting->DualStandby)
    {
        g_FrameworkMng.SimStandBy[0] = FALSE;
        g_FrameworkMng.SimStandBy[1] = TRUE;
    }
    else
    {
        /* error */
    }

    if (IF_SETTING_TIME_FORMAT_12H == PhoneSetting->TimeDisplay.TimeFormat)
    {
        g_FrameworkMng.TimeFormat.HourFormat = FRAMEWORK_HOUR_FORMAT_12H;
    }
    else if (IF_SETTING_TIME_FORMAT_24H == PhoneSetting->TimeDisplay.TimeFormat)
    {
        g_FrameworkMng.TimeFormat.HourFormat = FRAMEWORK_HOUR_FORMAT_24H;
    }
    else
    {
        /* error */
    }

    if (IF_SETTING_TIME_SHOW == PhoneSetting->TimeDisplay.TimeDisplay)
    {
        g_FrameworkMng.TimeFormat.TimeDisplay = FRAMEWORK_TIME_SHOW;
    }
    else if (IF_SETTING_TIME_HIDE == PhoneSetting->TimeDisplay.TimeDisplay)
    {
        g_FrameworkMng.TimeFormat.TimeDisplay = FRAMEWORK_TIME_HIDE;
    }
    else
    {
        /* error */
    }

    g_FrameworkMng.AutoGuardOn    = PhoneSetting->AutoGuardOn;
    g_FrameworkMng.AutoGuardDelay = PhoneSetting->AutoGuardDelay;
    g_FrameworkMng.KeyguardCodeOn = PhoneSetting->KeyguardOn;

    g_FrameworkMng.StartupToneOn = PhoneSetting->StartupToneOn;

    if (IF_SETTING_STANDBY_SCREEN_ON == PhoneSetting->StandbyScreenMode)
    {
        g_FrameworkMng.StandbyScreenMode = TRUE;
    }

    if (TRUE == PhoneSetting->WelcomeNoteOn)
    {
        g_FrameworkMng.WelcomeNote = (INT8 *)Hal_Mem_Alloc(IF_SETTING_MAX_WELCOME_NOTE_LEN);
        memcpy(g_FrameworkMng.WelcomeNote, PhoneSetting->WelcomeNote,
            IF_SETTING_MAX_WELCOME_NOTE_LEN);
    }

    g_FrameworkMng.FlightModeOn = PhoneSetting->FlightModeOn;
}


/**
 * initialize the apps exclude settings
 * param (in) Reboot: BOOL
 * return  VOID
 */
VOID Framework_Init_Config(BOOL Reboot)
{
    UINT32            NvmLen;
    NV_UI_Framework_t Nvm;
    UINT8             i;
    Framework_App_t   *App;

    /* initiate APPs */
    if (Reboot)
    {
        Contacts_Reboot_Req();
        i = 2; // exclude settings and contacts
    }
    else
    {
        i = 1; // exclude settings
    }
    for (; i < UI_MAX_APP_NUM; i++)
    {
        if (TRUE == g_UiAppMng[i].AppFlg)
        {
            g_UiAppMng[i].InitFunc();
        }
    }

    /* read NVM */
    NvmLen = sizeof(NV_UI_Framework_t);
    if (NvmLen == UI_NV_Read_Req(NV_SECTION_UI_FRAMEWORK, 0, NvmLen, (UINT8 *)(&Nvm)))
    {
        /* Save Go to list, index starts from 1 */
        g_FrameworkMng.GotoAppNum = 0;
        for (i = 0; i < NV_FRAMEWORK_MAX_APP_NUM; i++)
        {
            if (LV_LANG_TXT_ID_NONE == Nvm.AppNameTextId[i])
            {
                break;
            }

            App = g_FrameworkMng.AppList;
            while (NULL != App)
            {
                if (Nvm.AppNameTextId[i] == App->NameTextId)
                {
                    g_FrameworkMng.GotoAppNum++;
                    App->GotoIndex = g_FrameworkMng.GotoAppNum;
                    break;
                }

                App = App->Next;
            }
        }
    }
    else
    {
        /* error */
    }

    if (IF_FRAMEWORK_INIT_SILENT_RESET == g_FrameworkMng.PowerOnType)
    {
        Framework_Set_Phone_Ready_Status(TRUE);

#ifdef USE_LV_INTERPHONE_DEMO
        Interphone_Create_Status_Bar();
        Interphone_Create_Login();
#elif USE_LV_DEMO_128x64
        Demo_128x64_Create();
#else
        Framework_Display_Status_Bar(TRUE);
        Framework_Create_Desktop();
#endif
        return;
    }

    if (  (FRAMEWORK_SIM_STATUS_UNKNOWN != g_FrameworkMng.SimStatus[0])
       && (FRAMEWORK_SIM_STATUS_UNKNOWN != g_FrameworkMng.SimStatus[1])
       && (ACT_ID_BOOT_ANIMATION == Nav_Get_Top()))
    {   /* Dual SIM ready */
        printf("%s: InitComplete %d, RebootProc %d\n",
               __FUNCTION__, g_FrameworkMng.InitComplete, g_FrameworkMng.RebootProc);
        if (FALSE == g_FrameworkMng.InitComplete)
        {
            if (FRAMEWORK_REBOOT_WAIT_SIM_STATUS == g_FrameworkMng.RebootProc)
            {
                g_FrameworkMng.RebootProc = FRAMEWORK_REBOOT_NULL;

                if (TRUE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_1))
                {
                    MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_1);
                }
                if (TRUE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_2))
                {
                    MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_2);
                }
            }

            g_FrameworkMng.InitComplete = TRUE;
#ifndef BUILD_IN_PC_SIMULATOR
            if (TRUE == g_FrameworkMng.StartupToneOn)
            {
                printf("%s: play power on tone\n", __FUNCTION__);
                AudioHAL_SetResBufCnt(20);
                Setting_Play_System_Tone_Req(Framework_Power_On_Tone_End_Cb);
            }
            else
            {
                Framework_Power_On_Tone_End_Cb(NULL);
            }
#else
            Framework_Power_On_Tone_End_Cb(NULL);
#endif
        }
    }
}

/**
 * Reboot from power off charging mode
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Reboot_Delay_Cb(lv_task_t * Task)
{
    g_FrameworkMng.RebootProc = FRAMEWORK_REBOOT_WAIT_SIM_STATUS;
    Framework_Init_Config(TRUE);
}

/**
 * Reboot from power off charging mode
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Reboot(VOID)
{
    Framework_App_t *Apps;
    lv_task_t       *Task;

    printf("%s\n", __FUNCTION__);

    if (0 != (g_FrameworkMng.CnfBitmap & 0x01))
    {
        printf("%s: wait for Settings_Init_Cnf\n", __FUNCTION__);
        return;
    }

    if (g_FrameworkMng.ImgSimSta[0])
    {
        lv_obj_set_hidden(g_FrameworkMng.ImgSimSta[0], FALSE);
    }

    Nav_Reset();
    Framework_Calendar_Reset_Req();

    Framework_Set_Phone_Ready_Status(FALSE);
    Framework_Create_Boot_Animation();

    lv_task_del(g_FrameworkMng.Task);
    g_FrameworkMng.PowerOnType = IF_FRAMEWORK_INIT_NORMAL;
    g_FrameworkMng.SignalBar[0]  = MMI_MODEM_SIGNAL_BAR_0;
    g_FrameworkMng.SignalBar[1]  = MMI_MODEM_SIGNAL_BAR_0;
    Apps = g_FrameworkMng.AppList->Next; // not clear settings app
    while (Apps)
    {
        g_FrameworkMng.AppList->Next = Apps->Next;
        Hal_Mem_Free(Apps);
        Apps = g_FrameworkMng.AppList->Next;
    }

    Task = lv_task_create(Framework_Reboot_Delay_Cb, 2000, LV_TASK_PRIO_HIGHEST, NULL);
    lv_task_once(Task);
}


/**
 * Callback function for handling key pressed on Charge_Animation interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Framework_Charge_Animation_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_LONGPRESS == Key_Sta)
    {
        if (KEY_END == Key_Val)
        {
#if 0
            Hal_Power_Off(HAL_TYPE_REBOOT);
#else
            g_FrameworkMng.RebootProc = FRAMEWORK_REBOOT_ONGOING;
            Framework_Reboot();
#endif
        }
    }

    return(1);
}


/**
 * Create Charge_Animation interface
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Create_Charge_Animation(VOID)
{
    UI_FullScreen_Label_Desc_t *FullScrnLblDesc;
    Nav_Func_List_t            FuncList;

    FullScrnLblDesc =
        (UI_FullScreen_Label_Desc_t *)Hal_Mem_Alloc(sizeof(UI_FullScreen_Label_Desc_t));
    Hal_Mem_Set(FullScrnLblDesc, 0, sizeof(UI_FullScreen_Label_Desc_t));

    FullScrnLblDesc->BatteryLabel.SymbolId = Framework_Get_Battery_Symbol(
        g_FrameworkMng.BatteryStatus);
    FullScrnLblDesc->BatteryLabel.TxtId = LV_LANG_TXT_ID_NONE;
    FullScrnLblDesc->BatteryLabel.TxtFont     = LV_THEME_SIMPLE_FONT_BIG;
    FullScrnLblDesc->BatteryLabel.SymbolAlign = LV_LABEL_ALIGN_CENTER;
    FullScrnLblDesc->BatteryLabel.LabelAlign  = LV_ALIGN_IN_LEFT_MID;
    /* FullScrnLblDesc->ChargeLabel.SymbolId     = LV_SYMBOL_CHARGE; */
    FullScrnLblDesc->ChargeLabel.SymbolAlign = LV_LABEL_ALIGN_CENTER;
    FullScrnLblDesc->ChargeLabel.LabelAlign  = LV_ALIGN_IN_LEFT_MID;
    FullScrnLblDesc->KeyFunc                 = Framework_Charge_Animation_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_FullScreen_Label_Create;
    FuncList.OnCreate       = Framework_Charge_Animation_OnCreate;
    FuncList.OnRestoreState = Framework_Charge_Animation_OnRestoreState;
    FuncList.OnSaveState    = Framework_Charge_Animation_OnSaveState;
    FuncList.OnDestroy      = Framework_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CHARGE_ANIMATION, &FuncList, FullScrnLblDesc);
} /* Framework_Create_Charge_Animation */


/**
 * Framework module initialization complete
 * param (in) VOID
 * return  VOID
 */
VOID Framework_Init_Complete(VOID)
{
    if (NULL != g_FrameworkMng.WelcomeNote)
    {
        Framework_Create_Welcome_Note();
    }
    else
    {
        Framework_Set_Phone_Ready_Status(TRUE);

        #ifdef USE_LV_INTERPHONE_DEMO
        Interphone_Create_Login();
        #elif USE_LV_DEMO_128x64
        Demo_128x64_Create();
        #else
        Framework_Create_Desktop();
        #endif
    }

    printf("%s: sim1 status %d, sim2 status %d\n",
           __FUNCTION__, g_FrameworkMng.SimStatus[0], g_FrameworkMng.SimStatus[1]);

    if (FRAMEWORK_SIM_STATUS_PRESENT == g_FrameworkMng.SimStatus[0])
    {
        Setting_Set_Sim_Status(MMI_MODEM_SIM_1, TRUE);
        Contacts_Sim_Status_Ind(MMI_MODEM_SIM_1, TRUE);
    }
    else
    {
        Setting_Set_Sim_Status(MMI_MODEM_SIM_1, FALSE);
        Contacts_Sim_Status_Ind(MMI_MODEM_SIM_1, FALSE);
    }

    if (FRAMEWORK_SIM_STATUS_PRESENT == g_FrameworkMng.SimStatus[1])
    {
        Setting_Set_Sim_Status(MMI_MODEM_SIM_2, TRUE);
        Contacts_Sim_Status_Ind(MMI_MODEM_SIM_2, TRUE);
    }
    else
    {
        Setting_Set_Sim_Status(MMI_MODEM_SIM_2, FALSE);
        Contacts_Sim_Status_Ind(MMI_MODEM_SIM_2, FALSE);
    }
}


/**
 * Result for checking PIN code from setting module
 * param (in) SimId: MMI_MODEM_SIM_ID
 * param (in) Result: SETTING_RESULT
 * return  VOID
 */
VOID Framework_Check_PIN_Cnf(MMI_MODEM_SIM_ID SimId, SETTING_RESULT Result)
{
    if (SETTING_ERROR == Result)
    {   /* PIN and PUK check failure, the SIM is locked */
        g_FrameworkMng.SimStatus[SimId] = FRAMEWORK_SIM_STATUS_ABSENT;
    }
    else
    {
        g_FrameworkMng.SimStatus[SimId] = FRAMEWORK_SIM_STATUS_PRESENT;
    }

    if (MMI_MODEM_SIM_1 == SimId)
    {
        if (FRAMEWORK_SIM_STATUS_PRESENT_PIN == g_FrameworkMng.SimStatus[1])
        {
            Setting_Check_PIN_Req(MMI_MODEM_SIM_2, Framework_Check_PIN_Cnf);
        }
        else
        {
            Framework_Init_Complete();
        }
    }
    else
    {
        Framework_Init_Complete();
    }
}


/**
 * Callback function for the end of power on
 * param (in) SimId: MMI_MODEM_SIM_ID
 * return  VOID
 */
VOID Framework_Power_On_Tone_End_Cb(VOID * Para)
{
#ifndef BUILD_IN_PC_SIMULATOR
    if (TRUE == g_FrameworkMng.StartupToneOn) {
        AudioHAL_SetResBufCnt(4);
    }
#endif
    Setting_Power_On_Tone_End_Ind();
    /* Destroy Boot_Animation interface */
    Nav_Back(ACT_ID_ANY);

#ifdef USE_LV_INTERPHONE_DEMO
    Interphone_Create_Status_Bar();
#elif USE_LV_DEMO_128x64

#else
    Framework_Display_Status_Bar(TRUE);
#endif
    if (FRAMEWORK_SIM_STATUS_PRESENT_PIN == g_FrameworkMng.SimStatus[0])
    {
        Setting_Check_PIN_Req(MMI_MODEM_SIM_1, Framework_Check_PIN_Cnf);
    }
    else if (FRAMEWORK_SIM_STATUS_PRESENT_PIN == g_FrameworkMng.SimStatus[1])
    {
        Setting_Check_PIN_Req(MMI_MODEM_SIM_2, Framework_Check_PIN_Cnf);
    }
    else
    {   /* Dual SIM absent */
        Framework_Init_Complete();
    }
}


/**
 * SIM status changed from modem
 * param (in) SimId: MMI_MODEM_SIM_ID
 * return  VOID
 */
VOID Phone_Modem_Sim_Status_Ind(MMI_Modem_Sim_Status_t *SimStatus)
{
    if (NULL == SimStatus)
    {
        /* error */
        return;
    }

#if 0
    if (ACT_ID_CHARGE_ANIMATION == g_FrameworkMng.InterfaceCtrl.InterfaceId)
    {
        /* error */
        Hal_Mem_Free(SimStatus);
        return;
    }
#endif

    printf("%s:old sim0 %d,old sim1 %d,simid %d,present %d\n",
           __FUNCTION__, g_FrameworkMng.SimStatus[0], g_FrameworkMng.SimStatus[1],
           SimStatus->SimId, SimStatus->SimPresent);
#ifdef USE_LV_INTERPHONE_DEMO
    if (MMI_MODEM_SIM_1 == SimStatus->SimId)
    {
        Interphone_Set_Sim_Status(SimStatus->SimPresent);
    }
#endif

    if (FRAMEWORK_SIM_STATUS_UNKNOWN == g_FrameworkMng.SimStatus[SimStatus->SimId])
    {
        if (TRUE == SimStatus->SimPresent)
        {
            if (  (MMI_MODEM_PIN1_REQUIRED == SimStatus->Pin1Status)
               || (MMI_MODEM_PIN2_REQUIRED == SimStatus->Pin1Status)
               || (MMI_MODEM_PIN1_BLOCKED_PUK1_REQUIRED == SimStatus->Pin1Status)
               || (MMI_MODEM_PIN2_BLOCKED_PUK2_REQUIRED == SimStatus->Pin1Status))
            {
                g_FrameworkMng.SimStatus[SimStatus->SimId] = FRAMEWORK_SIM_STATUS_PRESENT_PIN;
            }
            else if (MMI_MODEM_PIN_DISABLED == SimStatus->Pin1Status)
            {
                g_FrameworkMng.SimStatus[SimStatus->SimId] = FRAMEWORK_SIM_STATUS_PRESENT;
            }
            else
            {
                g_FrameworkMng.SimStatus[SimStatus->SimId] = FRAMEWORK_SIM_STATUS_ABSENT;
            }
        }
        else
        {
            g_FrameworkMng.SimStatus[SimStatus->SimId] = FRAMEWORK_SIM_STATUS_ABSENT;
        }
    }

    Hal_Mem_Free(SimStatus);

    if ((FRAMEWORK_SIM_STATUS_UNKNOWN != g_FrameworkMng.SimStatus[0])
        && (FRAMEWORK_SIM_STATUS_UNKNOWN != g_FrameworkMng.SimStatus[1]))
    {     /* Dual SIM ready */
        if (0 != (g_FrameworkMng.CnfBitmap & 0x01))
        { /* Wait for setting init cnf */
            return;
        }

        printf("%s: InitComplete %d, RebootProc %d\n",
               __FUNCTION__, g_FrameworkMng.InitComplete, g_FrameworkMng.RebootProc);

        if (IF_FRAMEWORK_INIT_SILENT_RESET == g_FrameworkMng.PowerOnType)
        {
            g_FrameworkMng.InitComplete = TRUE;
            g_FrameworkMng.PowerOnType = IF_FRAMEWORK_INIT_NORMAL;

            if (FALSE == g_FrameworkMng.FlightModeOn)
            {
                if (FALSE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_1))
                {
                    MMI_Modem_Power_Off_Req(MMI_MODEM_SIM_1, MMI_MODEM_SIM_DISABLE);
                }
                if (FALSE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_2))
                {
                    MMI_Modem_Power_Off_Req(MMI_MODEM_SIM_2, MMI_MODEM_SIM_DISABLE);
                }
            }

            if (FRAMEWORK_SIM_STATUS_PRESENT == g_FrameworkMng.SimStatus[0])
            {
                Setting_Set_Sim_Status(MMI_MODEM_SIM_1, TRUE);
                Contacts_Sim_Status_Ind(MMI_MODEM_SIM_1, TRUE);
            }
            else
            {
                Setting_Set_Sim_Status(MMI_MODEM_SIM_1, FALSE);
                Contacts_Sim_Status_Ind(MMI_MODEM_SIM_1, FALSE);
            }

            if (FRAMEWORK_SIM_STATUS_PRESENT == g_FrameworkMng.SimStatus[1])
            {
                Setting_Set_Sim_Status(MMI_MODEM_SIM_2, TRUE);
                Contacts_Sim_Status_Ind(MMI_MODEM_SIM_2, TRUE);
            }
            else
            {
                Setting_Set_Sim_Status(MMI_MODEM_SIM_2, FALSE);
                Contacts_Sim_Status_Ind(MMI_MODEM_SIM_2, FALSE);
            }
        }
        else if ((ACT_ID_BOOT_ANIMATION == Nav_Get_Top())
                 && (FRAMEWORK_REBOOT_ONGOING != g_FrameworkMng.RebootProc))
        {
            if (FALSE == g_FrameworkMng.InitComplete)
            {
                g_FrameworkMng.InitComplete = TRUE;

                if (FRAMEWORK_REBOOT_WAIT_SIM_STATUS == g_FrameworkMng.RebootProc)
                {
                    g_FrameworkMng.RebootProc = FRAMEWORK_REBOOT_NULL;

                    if (TRUE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_1))
                    {
                        MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_1);
                    }
                    if (TRUE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_2))
                    {
                        MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_2);
                    }
                }
                else
                {
                    if (FALSE == g_FrameworkMng.FlightModeOn)
                    {
                        if (FALSE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_1))
                        {
                            MMI_Modem_Power_Off_Req(MMI_MODEM_SIM_1, MMI_MODEM_SIM_DISABLE);
                        }
                        if (FALSE == Framework_Is_Sim_Standby(MMI_MODEM_SIM_2))
                        {
                            MMI_Modem_Power_Off_Req(MMI_MODEM_SIM_2, MMI_MODEM_SIM_DISABLE);
                        }
                    }
                }

#ifndef BUILD_IN_PC_SIMULATOR
                if (TRUE == g_FrameworkMng.StartupToneOn)
                {
                    printf("%s: play power on tone\n", __FUNCTION__);
                    AudioHAL_SetResBufCnt(20);
                    Setting_Play_System_Tone_Req(Framework_Power_On_Tone_End_Cb);
                }
                else
                {
                    Framework_Power_On_Tone_End_Cb(NULL);
                }
#else
                Framework_Power_On_Tone_End_Cb(NULL);
#endif
            }
        }
    }
} /* MMI_Modem_Sim_Status_Ind */


/**
 * Confirmation for setting module initiation
 * param (in) PhoneSetting: Setting_Phone_Setting_t *
 * return  VOID
 */
VOID Setting_Init_Cnf(Setting_Phone_Setting_t *PhoneSetting)
{
    if (NULL == PhoneSetting)
    {
        /* error */
        return;
    }

    if (0 == (g_FrameworkMng.CnfBitmap & 0x01))
    {
        printf("%s: wrong cnf\n", __FUNCTION__);
        return;
    }

    g_FrameworkMng.CnfBitmap &= ~0x01;

    Framework_Save_Phone_Setting(PhoneSetting);
    Hal_Mem_Free(PhoneSetting);

    if (IF_FRAMEWORK_INIT_CHARGE == g_FrameworkMng.PowerOnType)
    {
        if (FRAMEWORK_REBOOT_NULL != g_FrameworkMng.RebootProc)
        {
            printf("%s: reboot\n", __FUNCTION__);
            Framework_Reboot();
        }
        return;
    }

    Framework_Init_Config(FALSE);
} /* Setting_Init_Cnf */

static void low_power_ind_cb(void * para)
{
    (void)para;
    printf("%s\n", __FUNCTION__);

#if !FAKE_BATTERY
    if(0 == Hal_Pm_Get_State()) Hal_Pm_WakeUp();

#endif
}

void lowbattery_handle_destroy(void)
{
    if(NULL != lowbattery_monitor_task)
    {
        lv_task_del(lowbattery_monitor_task);
    }

}

static void lowbattery_task(lv_task_t * Task)
{
    if(HAL_CHG_CONNECTED != Hal_Charger_Get_Status())
    {
        if(Hal_Battery_Get_Status() == HAL_BAT_EMPTY)
        {
            printf("power off in lowbattery_task\n");
            Framework_Switch_Off_Handle();
        }
    }
}

static void lowbattery_handle_init(void)
{
    lowbattery_monitor_task = lv_task_create(lowbattery_task, 5000, LV_TASK_PRIO_MID, NULL);
}

/**
 * Initiate framework
 * param (in) Type: IF_FRAMEWORK_INIT_TYPE
 * return  VOID
 */
VOID Framework_Init_Req(IF_FRAMEWORK_INIT_TYPE Type)
{
    Nav_Init();

    Hal_Mem_Set(&g_FrameworkMng, 0, sizeof(Framework_Mng_t));
    g_FrameworkMng.SuspendEnable = TRUE;
    g_FrameworkMng.LcdStatus   = TRUE;
    g_FrameworkMng.PowerOnType = Type;

    Hal_Register_Charger_Status_Ind(Framework_Update_Charger_Status);
    lowbattery_handle_init();

    if (Type == IF_FRAMEWORK_INIT_NORMAL)
    {
        Framework_Create_Boot_Animation();

        g_FrameworkMng.SignalBar[0]  = MMI_MODEM_SIGNAL_BAR_0;
        g_FrameworkMng.SignalBar[1]  = MMI_MODEM_SIGNAL_BAR_0;
        g_FrameworkMng.BatteryStatus = HAL_BAT_EMPTY;

        g_FrameworkMng.CnfBitmap |= 0x01;

        g_UiAppMng[0].InitFunc(); // Setting_Init_Req();
    }
    else if (Type == IF_FRAMEWORK_INIT_CHARGE)
    {
        g_FrameworkMng.CnfBitmap |= 0x01;
        g_UiAppMng[0].InitFunc(); // Setting_Init_Req(), not set g_FrameworkMng.CnfBitmap |= 0x01
        g_UiAppMng[1].InitFunc(); // Contacts_Init_Req()
        Framework_Calendar_Init_Req();
        Framework_Alarm_Init_Req();

        g_FrameworkMng.BatteryStatus = Framework_Get_Battery_Level(Hal_Battery_Get_Status());
        g_FrameworkMng.ChargeFlg     = TRUE;

        Framework_Set_Phone_Ready_Status(TRUE);

        Framework_Create_Charge_Animation();

        g_FrameworkMng.Task = lv_task_create(Framework_PowerOff_1s_Update_Cb, 1000, LV_TASK_PRIO_HIGH, NULL);
    }
    else if (Type == IF_FRAMEWORK_INIT_ALARM)
    {
#if 0 // ril not support power off alarm mode, alarm ringing during power off will start up normally
        g_FrameworkMng.BatteryStatus = Framework_Get_Battery_Level(Hal_Battery_Get_Status());
        g_FrameworkMng.AlarmFlg      = TRUE;

        Framework_Calendar_Init_Req();
        Framework_Alarm_Init_Req();
#else // start up normally
        Framework_Create_Boot_Animation();

        g_FrameworkMng.SignalBar[0]  = MMI_MODEM_SIGNAL_BAR_0;
        g_FrameworkMng.SignalBar[1]  = MMI_MODEM_SIGNAL_BAR_0;
        g_FrameworkMng.BatteryStatus = HAL_BAT_EMPTY;

        g_FrameworkMng.CnfBitmap |= 0x01;

        g_UiAppMng[0].InitFunc(); // Setting_Init_Req();
#endif
    }
    else if (Type == IF_FRAMEWORK_INIT_SILENT_RESET)
    {
        if (0 == Hal_Get_Backlight_Status())
        {
            Framework_Set_Lcd_Status(FALSE);
        }
        printf("%s: silent reset, LcdStatus %d\n", __FUNCTION__, g_FrameworkMng.LcdStatus);
        g_FrameworkMng.SignalBar[0]  = MMI_MODEM_SIGNAL_BAR_0;
        g_FrameworkMng.SignalBar[1]  = MMI_MODEM_SIGNAL_BAR_0;
        g_FrameworkMng.BatteryStatus = HAL_BAT_EMPTY;

        g_FrameworkMng.CnfBitmap |= 0x01;

        g_UiAppMng[0].InitFunc(); // Setting_Init_Req();
    }
    else
    {
        /* error */
    }
} /* Framework_Init_Req */

/**
 * show power on logo of phone
 * param (in) Type: void
 * return  VOID
 */
void phone_poweron_logo(void)
{
    lv_obj_t * obj = lv_obj_create(lv_scr_act(), NULL);
    lv_obj_set_size(obj, FP_HOR_RES, FP_VER_RES);
    lv_obj_set_style_local_bg_color(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
    lv_obj_set_style_local_bg_opa(obj, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_refr_now(NULL);
    lv_obj_del(obj);
}

/**
 * start up UI of phone
 * param (in) Type: void
 * return  VOID
 */
VOID Ui_Phone_main(VOID)
{
    HAL_POWERUP_REASON Reason = Hal_Powerup_Get_Reason();
    printf("%s: powerup reason %d\n", __FUNCTION__, Reason);

    #ifdef UI_COMMON_DUMMY
    UI_Common_Test_Main();
    #else
    UI_Normal_Common_init();
    #endif

    Hal_Set_Voice_Call_Status(VOICE_CALL_END);

#if USE_LV_WATCH_MODEM_ADAPTOR
    // read FlightModeOn from NVM
    UINT8  nvData = 0;
    UINT32 nvOffset = sizeof(NV_Setting_Dual_Setting_t) + sizeof(NV_Setting_Tone_Setting_t)
                      + sizeof(NV_Setting_Display_Setting_t) + sizeof(NV_Setting_Profile_Setting_t)
                      + sizeof(NV_Setting_Time_Setting_t) + sizeof(NV_Setting_Call_Setting_t);
    UI_NV_Read_Req(NV_SECTION_UI_SETTINGS, nvOffset + 9 + NV_SETTING_MAX_WELCOME_NOTE_STR_LEN, 1, &nvData);
    printf("%s: FlightModeOn = %d\n", __FUNCTION__, nvData);
    MMI_ModemAdp_Init_Req(nvData);
    phone_message_handle_init();
#else
    MMI_Modem_Power_Up_Req(MMI_MODEM_SIM_1);
#endif

#if MMI_MODEM_SMS_STORE_IN_FILE != 0
    MMI_Modem_Sms_File_Init();
#endif

    Hal_Mem_Check_Start();

    Hal_Register_Low_Power_Ind(low_power_ind_cb);

    if ((HAL_POWERUP_ONKEY == Reason) || (HAL_POWERUP_REBOOT == Reason))
    {
        // unknow is for soft reboot
        Framework_Init_Req(IF_FRAMEWORK_INIT_NORMAL);
    }
    else if (HAL_POWERUP_BAT == Reason || HAL_POWERUP_USB == Reason)
    {
        Framework_Init_Req(IF_FRAMEWORK_INIT_CHARGE);
    }
    else if (HAL_POWERUP_RTC_ALARM == Reason)
    {
        Framework_Init_Req(IF_FRAMEWORK_INIT_ALARM);
    }
    else if (HAL_POWERUP_SILENT_RESET == Reason)
    {
        Framework_Init_Req(IF_FRAMEWORK_INIT_SILENT_RESET);
    }
    else
    {
        printf("%s: error mode %d !\n", __FUNCTION__, Reason);
    }
}

/**
 * Set sleep LCD only
 * param (in) Enable: BOOL
 * return VOID
 */
void Framework_Set_Sleep_Lcd_Only(BOOL Enable)
{
    printf("%s : %d\n", __FUNCTION__, Enable);
    g_FrameworkMng.SleepLcdOnly = Enable;

    if((TRUE == Enable) && (0 == Hal_Pm_Get_State())) {
        Hal_Pm_WakeUp();
    }
}


/**
 * Get phone ready status
 * param (in) VOID
 * return BOOL: TRUE if phone is ready, otherwise FALSE
 */
BOOL Framework_Get_Phone_Ready_Status(VOID)
{
    //printf("%s: phone ready %d\n", __FUNCTION__, g_FrameworkMng.PhoneReady);
    return g_FrameworkMng.PhoneReady;
}


/**
 * Set phone ready status
 * param (in) BOOL: TRUE if phone is ready, otherwise FALSE
 * return VOID
 */
VOID Framework_Set_Phone_Ready_Status(BOOL PhoneReady)
{
    printf("%s: old %d, new %d\n", __FUNCTION__, g_FrameworkMng.PhoneReady, PhoneReady);
    g_FrameworkMng.PhoneReady = PhoneReady;
}
